#include "videoLooper.h"


//--------------------------------------------------------------
void videoLooper::setup(int width, int height){	 
	
	
	for (int i = 0; i < NUM_FRAMES_MEMORY; i++){
		videoTexture[i].allocate(width, height, GL_RGBA);
		timeOfFrame[i] = 0;
	}
	
	bLooping 		= false;
	currFrame		= 0; 
	nFrameRecorded 	= 0;
	lastUpdateTime	= ofGetElapsedTimef();
	loopTime		= 0.5f;
	loopFrame		= 0;
	bFirstFrameRecording	= false;
	bRecording 				= false;
	
	
	videoFrameWithAlpha 	= new unsigned char [width * height * 4];
	
}


//--------------------------------------------------------------
void videoLooper::update(ofVideoGrabber * vidGrabber, videoMasker * mask){
		
	//---------------------------------------------------------- loop 
	if (bRecording == true){
		if (vidGrabber->isFrameNew()){
			
			if (bFirstFrameRecording == true){
				startTime = timeOfFrame[currFrame];
				bFirstFrameRecording = false;
			}
			currFrame = nFrameRecorded;
			
			
		
			int nPixels = vidGrabber->width * vidGrabber->height;
			unsigned char * grayTmp = mask->grayMask.getPixels();	
			for (int i = 0; i < nPixels; i++){
				videoFrameWithAlpha[i*4 + 0] = vidGrabber->getPixels()[i*3];
				videoFrameWithAlpha[i*4 + 1] = vidGrabber->getPixels()[i*3+1];
				videoFrameWithAlpha[i*4 + 2] = vidGrabber->getPixels()[i*3+2];
				videoFrameWithAlpha[i*4 + 3] = grayTmp[i];
			}
			videoTexture[nFrameRecorded].loadData(videoFrameWithAlpha, vidGrabber->width, vidGrabber->height, GL_RGBA);
			//videoTexture[nFrameRecorded].loadData(vidGrabber->getPixels(), vidGrabber->width, vidGrabber->height, GL_RGB);
			timeOfFrame[nFrameRecorded] = ofGetElapsedTimef();
			
			nFrameRecorded ++;
			nFrameRecorded %= NUM_FRAMES_MEMORY;
		}
	} 
	
	if (bLooping) {
		float diffTime = ofGetElapsedTimef() - lastUpdateTime;
		if (!bLoopForward){
			loopTime -= diffTime;
			if (loopTime < startTime){
				float over = startTime - loopTime;
				loopTime = startTime;
				loopTime += over;
				bLoopForward = true;
			} 
		} else {
			loopTime += diffTime;
			if (loopTime > endTime){
			
				float over = loopTime - endTime;
				loopTime = endTime;
				loopTime -= over;
			
				
				bLoopForward = false;
			} 
		}
		
		
		int start 	= nFrameRecorded; 
		int end 	= (nFrameRecorded + NUM_FRAMES_MEMORY-1);
		for (int i = start; i < end; i++){
			int posa = i % NUM_FRAMES_MEMORY;
			int posb = (i+1) % NUM_FRAMES_MEMORY;
			float timea = timeOfFrame[posa];
			float timeb = timeOfFrame[posb];
			
			
			if (loopTime > timea && loopTime <= timeb){
				loopFrame = posb;
				continue;
			}
			
		}
		lastUpdateTime	= ofGetElapsedTimef();
	}
	
	//---------------------------------------------------------- 
}

//--------------------------------------------------------------
void videoLooper::draw(){
	
	ofEnableAlphaBlending();
	if (bLooping == true){
		videoTexture[loopFrame].draw(0,0,320 * 3, 240 * 3);
	}
	ofDisableAlphaBlending();
}


//--------------------------------------------------------------
void videoLooper::startRecording(){
	if (bRecording == false){
		bLooping = false;
		bRecording = true;
		recordingTimer = ofGetElapsedTimef();
	}
}

//--------------------------------------------------------------
void videoLooper::endRecording(){
	endTime 		= timeOfFrame[currFrame];
	float duration  = ofGetElapsedTimef() - recordingTimer;
	startTime 		= endTime - duration;
	loopTime		= endTime;
	bRecording 		= false;
		
}

//--------------------------------------------------------------
void videoLooper::setLooping(bool bLoop){
	bLooping = bLoop;
	if (bLooping){
		bLoopForward 	= false;
		loopFrame		= currFrame;
		bLooping  		= true;
		lastUpdateTime	= ofGetElapsedTimef();
	}
}
